package com.scs.application.modules.sys.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.scs.application.core.consts.Const;
import com.scs.application.core.exception.BusinessException;
import com.scs.application.core.query.QueryContext;
import com.scs.application.core.service.BaseServiceImpl;
import com.scs.application.core.service.IBaseFileService;
import com.scs.application.core.utils.BeanUtils;
import com.scs.application.core.utils.FileUtils;
import com.scs.application.core.utils.StringUtils;
import com.scs.application.core.utils.Tools;
import com.scs.application.modules.sys.dto.DictDTO;
import com.scs.application.modules.sys.entity.DictType;
import com.scs.application.modules.sys.mapper.DictTypeMapper;
import com.scs.application.modules.sys.service.DictTypeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 */
@Service
@Slf4j
public class FileDictTypeServiceImpl extends BaseServiceImpl<DictTypeMapper, DictType> implements DictTypeService, IBaseFileService<DictType, DictDTO> {

    @Override
    public boolean removeCascadeById(Serializable id) {
        List<DictType> dictTypes = list();
        for (DictType dictType : dictTypes) {
            if (id.equals(dictType.getId())) {
                FileUtils.deleteFile(Const.DATA_VIEW_DICT_SRC + dictType.getCode() + ".json");
                break;
            }
        }
        return true;
    }

    @Override
    public DictType getById(Serializable id) {
        DictType dictType = null;
        List<DictType> dictTypes = list();
        for (DictType dictType1 : dictTypes) {
            if (id.equals(dictType1.getId())) {
                dictType = dictType1;
                break;
            }
        }
        return dictType;
    }

    @Override
    public boolean removeCascadeByIds(Collection<? extends Serializable> idList) {
        List<DictType> dictTypes = list();
        for (DictType dictType : dictTypes) {
            if (idList.contains(dictType.getId())) {
                FileUtils.deleteFile(Const.DATA_VIEW_DICT_SRC + dictType.getCode() + ".json");
            }
        }
        return true;
    }

    @Override
    public Page<DictType> page(QueryContext context) {
        List<DictType> flows = list(context);
        return filePage(context, flows);
    }

    @Override
    public List<DictType> list() {
        QueryContext context = new QueryContext();
        return list(context);
    }

    @Override
    public List<DictType> list(QueryContext context) {
        List<DictDTO> dictDTOs = getDTOList();
        List<DictType> dictTypes = Lists.newArrayListWithCapacity(dictDTOs.size());
        for (DictDTO dictDTO : dictDTOs) {
            DictType dictType = new DictType();
            BeanUtils.copyProperties(dictDTO, dictType);
            dictTypes.add(dictType);
        }
        if (context != null && context.getParams() != null) {
            String code = context.getParams().get("code") != null ? context.getParams().get("code").toString() : "";
            String name = context.getParams().get("name") != null ? context.getParams().get("name").toString() : "";
            dictTypes = dictTypes.stream().filter(dictType -> (StringUtils.isNotBlank(code) ? dictType.getCode().indexOf(code) > -1 : true)
                    && (StringUtils.isNotBlank(name) ? dictType.getName().indexOf(name) > -1 : true)).collect(Collectors.toList());
        }
        return dictTypes;
    }

    @Override
    public DictDTO getDictDTOByCode(String dictTypeCode) {
        DictDTO dictDTO = new DictDTO();
        setDictDTO(dictDTO, Const.getDictSrc() + dictTypeCode + ".json");
        return dictDTO;
    }

    @Override
    public List<DictDTO> getDTOList() {
        return getDTOList(Const.getDictSrc());
    }

    @Override
    public <DictType> boolean saveBatch(Class<DictType> modelClass, Collection<DictType> entityList, int batchSize) {
        return false;
    }

    @Override
    public boolean saveOrUpdate(DictType dictType) {
        List<DictType> dictTypes = list();
        if (dictType.getId() == null) {
            dictType.setId(StringUtils.getIdStr());
        } else {
            dictTypes.stream().filter(dict -> dictType.getCode().equalsIgnoreCase(dict.getCode())
                    && !dictType.getId().equalsIgnoreCase(dict.getId())).findAny().ifPresent(dict -> {
                throw new BusinessException("Key已经存在，请重新命名！");
            });
        }
        File path = new File(Const.DATA_VIEW_DICT_SRC);
        if (!path.exists()) {
            path.mkdirs();
        }

        String fileNameWithPath = Const.DATA_VIEW_DICT_SRC + dictType.getCode() + ".json";

        if (dictType.getGmtCreate() == null) {
            dictType.setGmtCreate(LocalDateTime.now());
            dictType.setCreator(Tools.getHostName());
        } else {
            dictType.setGmtModified(LocalDateTime.now());
            dictType.setModifier(Tools.getHostName());
        }
        DictDTO dictDTO = getDictDTOByCode(dictType.getCode());
        if (dictDTO == null) {
            dictDTO = new DictDTO();
        }
        BeanUtils.copyProperties(dictType, dictDTO);
        String result = JSON.toJSONString(dictDTO, SerializerFeature.PrettyFormat);
        FileUtils.writeTxtFile(fileNameWithPath, result);
        return true;
    }

    @Override
    public DictDTO getDTO(String fileSrc) {
        DictDTO dictDTO = new DictDTO();
        setDictDTO(dictDTO, fileSrc);
        if (StringUtils.isBlank(dictDTO.getCode()) || StringUtils.isBlank(dictDTO.getId())) {
            return null;
        }
        return dictDTO;
    }

    private void setDictDTO(DictDTO dictDTO, String fileNameWithPath) {
        String dataViewString = FileUtils.readFileStore(fileNameWithPath);
        if (StringUtils.isEmpty(dataViewString)) {
            return;
        }
        JSONObject jsonObject = JSONObject.parseObject(dataViewString);
        dictDTO.setId(jsonObject.getString("id"))
                .setCode(jsonObject.getString("code"))
                .setName(jsonObject.getString("name"))
                .setDescription(jsonObject.getString("description"));
        String strDictDataDTOS = jsonObject.getString("dictDataDTOS");
        if (StringUtils.isNotBlank(strDictDataDTOS)) {
            JSONArray jsonArray = JSONArray.parseArray(strDictDataDTOS);
            if (jsonArray != null && !jsonArray.isEmpty()) {
                List<DictDTO.DictDataDTO> dictDataDTOS = Lists.newArrayListWithCapacity(jsonArray.size());
                jsonArray.forEach(obj -> {
                    JSONObject jsonObj = JSONObject.parseObject(obj.toString());
                    DictDTO.DictDataDTO dictDataDTO = new DictDTO.DictDataDTO();
                    dictDataDTO.setId(jsonObj.getString("id"))
                            .setDictTypeId(jsonObj.getString("dictTypeId"))
                            .setDictTypeCode(jsonObj.getString("dictTypeCode"))
                            .setValue(jsonObj.getString("value"))
                            .setLabel(jsonObj.getString("label"))
                            .setSort(jsonObj.getInteger("sort"))
                            .setColor(jsonObj.getString("color"));
                    dictDataDTOS.add(dictDataDTO);
                });
                dictDTO.setDictDataDTOS(dictDataDTOS);
            }
        }
    }

    @Override
    public Boolean isSupport(Boolean flagProject) {
        return !flagProject;
    }
}
